{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# JavaScript 函数参数\n",
    "JavaScript 函数对参数的值没有进行任何的检查。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 函数显式参数(Parameters)与隐式参数(Arguments)\n",
    "函数显式参数在函数定义时列出。\n",
    "\n",
    "函数隐式参数在函数调用时传递给函数真正的值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参数规则\n",
    "JavaScript 函数定义显式参数时没有指定数据类型。\n",
    "\n",
    "JavaScript 函数对隐式参数没有进行类型检测。\n",
    "\n",
    "JavaScript 函数对隐式参数的个数没有进行检测。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 默认参数\n",
    "ES5 中如果函数在调用时未提供隐式参数，参数会默认设置为： undefined\n",
    "\n",
    "有时这是可以接受的，但是建议最好为参数设置一个默认值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "function myFunction(x, y){\n",
    "    y = y||999;\n",
    "    console.log(\"<1>：\"+y);\n",
    "    return y,x;//默认只返回最后一个\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<1>：999\n",
      "<2>：2\n",
      "<1>：999\n",
      "undefined\n",
      "undefined\n"
     ]
    }
   ],
   "source": [
    "console.log(\"<2>：\"+myFunction(2));\n",
    "\n",
    "var a = myFunction(4);\n",
    "console.log(a[0]);\n",
    "console.log(b[1]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果y已经定义 ， y || 返回 y, 因为 y 是 true, 否则返回 0, 因为 undefined 为 false。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 补充：return 返回多种值的方式\n",
    "在使用JS编程中，有时需要在一个方法返回两个个或两个以上的数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 使用数组的方式一"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "function setData(){\n",
    "    var data = new Array(\"test1\",999,true,undefined);\n",
    "    return data;\n",
    "}\n",
    "function getData(i){\n",
    "    var data = setData();\n",
    "    console.log(data[i]);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "true\n"
     ]
    }
   ],
   "source": [
    "getData(2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 使用数组的方式二"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "function setData(a, b){\n",
    "    a = a.toString()+\" test\";\n",
    "    return [a, b];\n",
    "}\n",
    "function getData(i, a, b){\n",
    "    var data = setData(a, b);\n",
    "    console.log(data[i]);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "anlzou test\n"
     ]
    }
   ],
   "source": [
    "getData(0,\"anlzou\",99);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 将数据封装到Json中返回"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "function setData(){\n",
    "    var info = {\"1\":\"test1\", \"2\":999, \"3\":true, \"undef\":undefined, 0:\"test\"};\n",
    "    return info;\n",
    "}\n",
    "function getData(i){\n",
    "    var data = setData();\n",
    "    console.log(data[i]);\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "undefined\n",
      "test\n",
      "test1\n",
      "test\n",
      "test1\n"
     ]
    }
   ],
   "source": [
    "getData(\"undef\");\n",
    "getData(0);\n",
    "getData(\"1\");\n",
    "getData(\"0\");\n",
    "getData(1);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 将数据放到Set中返回"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {},
   "outputs": [],
   "source": [
    "function setData(){\n",
    "    var info = new Set();\n",
    "    info.add(1);\n",
    "    info.add(2);\n",
    "    info.add(2);//不显示，不允许重复值\n",
    "    \n",
    "    return info;\n",
    "}\n",
    "function getData(){\n",
    "    var datas = setData();\n",
    "    for (data of datas){\n",
    "        console.log(data);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "getData();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 将数据放入Map中返回"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [],
   "source": [
    "function setData(){\n",
    "    var info = new Map([[ 'name', '张三' ],[ 'password', '123456' ]]);\n",
    "    return info;\n",
    "}\n",
    "function getData(){\n",
    "    var datas = setData();\n",
    "    for (data of datas){\n",
    "        console.log(data);\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 'name', '张三' ]\n",
      "[ 'password', '123456' ]\n"
     ]
    }
   ],
   "source": [
    "getData();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 简述js中 for in 与 for of 区别\n",
    "for in是ES5标准，遍历key. \n",
    "\n",
    "for of是ES6标准，遍历value.\n",
    "\n",
    "一个比较神奇的例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "foo\n",
      "arrCustom\n",
      "objCustom\n",
      "3\n",
      "5\n",
      "7\n"
     ]
    }
   ],
   "source": [
    "Object.prototype.objCustom = function () {}; \n",
    "Array.prototype.arrCustom = function () {};\n",
    "\n",
    "let iterable = [3, 5, 7];\n",
    "iterable.foo = \"hello\";\n",
    "\n",
    "for (let i in iterable) {\n",
    "    console.log(i); //  0, 1, 2, \"foo\", \"arrCustom\", \"objCustom\"\n",
    "}\n",
    "\n",
    "\n",
    "for (let i of iterable) {\n",
    "    console.log(i); // 3, 5, 7\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### js中map和set的区别\n",
    "set是一种关联式容器，其特性如下：\n",
    "\n",
    "- set以RBTree作为底层容器\n",
    "- 所得元素的只有key没有value，value就是key\n",
    "- 不允许出现键值重复\n",
    "- 所有的元素都会被自动排序\n",
    "- 不能通过迭代器来改变set的值，因为set的值就是键\n",
    " \n",
    "\n",
    "map和set一样是关联式容器，它们的底层容器都是红黑树，区别就在于map的值不作为键，键和值是分开的。它的特性如下：\n",
    "\n",
    "- map以RBTree作为底层容器\n",
    "- 所有元素都是键+值存在\n",
    "- 不允许键重复\n",
    "- 所有元素是通过键进行自动排序的\n",
    "- map的键是不能修改的，但是其键对应的值是可以修改的"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ES6 函数可以自带参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "15\n"
     ]
    }
   ],
   "source": [
    "function myFunction(x, y = 10) {\n",
    "    // y is 10 if not passed or undefined\n",
    "    return x + y;\n",
    "}\n",
    " \n",
    "console.log(myFunction(0, 2)); // 输出 2\n",
    "console.log(myFunction(5)); // 输出 15, y 参数的默认值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## arguments 对象\n",
    "JavaScript 函数有个内置的对象 arguments 对象。\n",
    "\n",
    "argument 对象包含了函数调用的参数数组。\n",
    "\n",
    "创建一个函数用来统计所有数值的和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "871"
      ]
     },
     "execution_count": 151,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = sumAll(1, 123, 500, 115, 44, 88);\n",
    " \n",
    "function sumAll() {\n",
    "    var i, sum = 0;\n",
    "    for (i = 0; i < arguments.length; i++) {\n",
    "        sum += arguments[i];\n",
    "    }\n",
    "    return sum;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过值传递参数\n",
    "在函数中调用的参数是函数的隐式参数。\n",
    "\n",
    "JavaScript 隐式参数通过值来传递：函数仅仅只是获取值。\n",
    "\n",
    "如果函数修改参数的值，不会修改显式参数的初始值（在函数外定义）。\n",
    "\n",
    "隐式参数的改变在函数外是不可见的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过对象传递参数\n",
    "在JavaScript中，可以引用对象的值。\n",
    "\n",
    "因此我们在函数内部修改对象的属性就会修改其初始的值。\n",
    "\n",
    "修改对象属性可作用于函数外部（全局变量）。\n",
    "\n",
    "修改对象属性在函数外是可见的。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Javascript (Node.js)",
   "language": "javascript",
   "name": "javascript"
  },
  "language_info": {
   "file_extension": ".js",
   "mimetype": "application/javascript",
   "name": "javascript",
   "version": "13.13.0"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "289.4px"
   },
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
